package compiler.ast;

import java.io.PrintStream;
import java.util.ArrayList;

import compiler.tac.BasicBlock;
import compiler.tac.ExitBlock;
import compiler.tac.ThreeAddressCode;

public class IfStatement extends Statement {
	Relation relation;
	ArrayList<Statement> body1;
	ArrayList<Statement> body2;
	
	public IfStatement(Relation rel, ArrayList<Statement> left, ArrayList<Statement> right) {
		this.relation = rel;
		this.body1 = left;
		this.body2 = right;
	}

	public void printDotFormat(PrintStream out, String node) {
		out.println(node+" [label=\"if\"];");
		
		out.println(node+"->"+node+"0;");
		relation.printDotFormat(out, node+"0");
		
		if (body1 != null) {
			String thenNode = node+"1";
			out.println(node+"->"+thenNode+";");
			out.println(thenNode+" [label=\"then\"];");
			int order = 0;
			for (Statement stmt : body1) {
				out.println(thenNode+"->"+thenNode+order+";");
				stmt.printDotFormat(out, thenNode+order);
				order++;
			}
		}

		if (body2 != null) {
			String elseNode = node+"2";
			out.println(node+"->"+elseNode+";");
			out.println(elseNode+" [label=\"else\"];");
			int order = 0;
			for (Statement stmt : body2) {
				out.println(elseNode+"->"+elseNode+order+";");
				stmt.printDotFormat(out, elseNode+order);
				order++;
			}
		}
	}

	@Override
	public BasicBlock toThreeAddressCode(ThreeAddressCode tac, BasicBlock prev,
			ExitBlock exit) {
		// create false block
		BasicBlock falseb = new BasicBlock();
		tac.addBlock(falseb);
		BasicBlock.add(prev, falseb);
		
		// fill false block
		if (body2 != null) {
			for (Statement stmt : body2) {
				falseb = stmt.toThreeAddressCode(tac, falseb, exit);
				
				if (falseb == null) {
					break;
				}
			}
		}

		// create true block
		BasicBlock trueb = new BasicBlock();
		tac.addBlock(trueb);

		// relation
		String t = relation.toThreeAddressCode(tac, prev);
		String lable = tac.getLable();
		prev.addBranchInstruction(relation.getBranchOprt(), t, trueb,lable);
		//lable = tac.getLable();
		//prev.addJumpInstruction(falseb, lable);
		BasicBlock.add(prev, trueb);
		
		// fill true block
		for (Statement stmt : body1) {
			trueb = stmt.toThreeAddressCode(tac, trueb, exit);
			
			if (trueb == null) {
				break;
			}
		}
		
		// decide next block
		BasicBlock next;
		if (trueb.size() == 0) {
			next = trueb;
		} else {
			next = new BasicBlock();
			tac.addBlock(next);
			BasicBlock.add(trueb, next);
		}
		
		// add jump instruction in the false block
		lable = tac.getLable();
		falseb.addJumpInstruction(next, lable);
		//trueb.addJumpInstruction(next, lable);
		BasicBlock.add(falseb, next);
		//BasicBlock.add(trueb, next);
 		return next;
	}
}